package com.sinodata.bsm.center.service.relation;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.sinodata.bsm.center.cache.RelationTypeCache;
import com.sinodata.bsm.center.cache.ResRelationCache;
import com.sinodata.bsm.center.dao.BaseDao;
import com.sinodata.bsm.center.engine.resource.health.ResHealthEngine;
import com.sinodata.bsm.center.service.resource.ResService;
import com.sinodata.bsm.center.util.spring.SpringContextHolder;
import com.sinodata.bsm.common.constants.RelationConstants;
import com.sinodata.bsm.common.vo.RelationType;
import com.sinodata.bsm.common.vo.Res;
import com.sinodata.bsm.common.vo.ResRelation;

/**
 * <p>
 * Description:
 * </p>
 * 
 * @author liulibo
 * @version 1.0
 * 
 * <p>
 * History:
 * 
 * Date Author Version Description
 * ---------------------------------------------------------------------------------
 * 2012-5-31 下午4:55:20 liulibo 1.0 To create
 * </p>
 * 
 * @since
 * @see
 */
@Service
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public class ResRelationService {

    @Autowired
    private BaseDao baseDao;

    @Autowired
    private ResRelationCache resRelationCache;
    @Autowired
    private RelationTypeCache relationTypeCache;

    /**
     * 增加资源间关系
     * 
     * @param resRelation
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void addResRelation(ResRelation resRelation) {
        baseDao.save(resRelation);
        resRelationCache.addResRelation(resRelation);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public void batchAddResRelation(List<ResRelation> resRelationList) throws Exception {
        baseDao.batchSave(resRelationList);
    }

    public RelationType findRelationTypeById(Long id) {
        return relationTypeCache.get(id);
    }

    public Set<RelationType> getSelfAndSubRelationType() {
        return relationTypeCache.getSelfAndSubRelationType(RelationConstants.FILIATION);
    }

    /**
     * 判断是否有关系对端节点
     * 
     * @param parentId
     * @param relationTypes
     * @return
     */
    public boolean hasChild(Long parentId, Set<Long> relationTypes) {
        List<ResRelation> relations = resRelationCache.getResRelationsOfRes(parentId);
        if (relations != null) {
            for (ResRelation resRelation : relations) {
                if (resRelation.getStartId().longValue() == parentId.longValue() && relationTypes.contains(resRelation.getRelationTypeId().longValue())) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 删除资源间关系
     * 
     * @param resRelation
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void removeResRelation(ResRelation resRelation) {
        baseDao.delete(resRelation);
        resRelationCache.removeResRelation(resRelation);
    }

    public void refreshResHealthStatus(Long resId) {
        Res res = SpringContextHolder.getBean(ResService.class).get(resId);
        ResHealthEngine.getInstance().refreshResFromParent(res);
    }

    /**
     * 删除一个资源的所有关系
     * 
     * @param resId
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void removeResRelationByResId(Long resId) {
        List<ResRelation> list = resRelationCache.getResRelationsOfRes(resId);
        if (list != null) {
            for (int i = list.size() - 1; i >= 0; i--) {
                baseDao.delete(list.get(i));
            }
        }
        resRelationCache.remove(resId);
    }

    /**
     * 删除一个资源的一条关系
     * 
     * @param resId
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void removeResRelationByResId(Long parentId, Long childId) {
        List<ResRelation> list = resRelationCache.getResRelationsOfRes(parentId);
        if (list != null) {
            for (int i = list.size() - 1; i >= 0; i--) {
                if (list.get(i).getStartId() == parentId.longValue() && list.get(i).getEndId() == childId.longValue()) {
                    baseDao.delete(list.get(i));
                    resRelationCache.removeResRelation(list.get(i));
                }
            }
        }

    }

    @Transactional(propagation = Propagation.REQUIRED)
    public void updateResRelationLabel(Long relId, String newLabel) {
        ResRelation rel = getById(relId);
        rel.setLabel(newLabel);
        baseDao.update(rel);
    }

    public ResRelation getById(Long relationId) {
        return resRelationCache.getById(relationId);
    }

    public List<ResRelation> getResRelationsOfRes(Long resId) {
        return resRelationCache.get(resId);
    }

    /**
     * 根据endid,找startId
     * @param endResId
     * @param relationTypeId
     * @return
     */
    public List<Long> getResByEndId(Long endResId, Long relationTypeId) {
        List<ResRelation> list = getResRelationsOfRes(endResId);
        List<Long> endResIds = new ArrayList<Long>();
        if (list != null)
            for (ResRelation rel : list) {
                if (rel.getEndId().equals(endResId) && rel.getRelationTypeId().equals(relationTypeId)) {
                    endResIds.add(rel.getStartId());
                }
            }
        return endResIds;
    }

    /**
     * 获取所有父子关系类别的ID
     * @return
     */
    public Set<Long> getSelfAndSubRelationTypeIds() {
        Set<RelationType> relationTypes = getSelfAndSubRelationType();
        Set<Long> relationTypesIds = new HashSet<Long>();
        for (RelationType type : relationTypes) {
            relationTypesIds.add(type.getId().longValue());
        }
        return relationTypesIds;
    }

}